package cn.amaake.magicplugin.nacos.autoconfigure;

import cn.amaake.magicplugin.nacos.config.NacosConfig;
import cn.amaake.magicplugin.nacos.module.NacosConfigModule;
import cn.amaake.magicplugin.nacos.module.RpcModule;
import cn.amaake.magicplugin.nacos.service.MagicSynchronizationService;
import cn.amaake.magicplugin.nacos.service.NacosClusterListener;
import cn.amaake.magicplugin.nacos.service.NacosDiscovery;
import cn.hutool.json.JSONUtil;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.ConfigType;
import com.alibaba.nacos.api.exception.NacosException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.ssssssss.magicapi.core.config.MagicAPIProperties;
import org.ssssssss.magicapi.core.config.MagicPluginConfiguration;
import org.ssssssss.magicapi.core.model.Plugin;
import org.ssssssss.magicapi.core.service.MagicAPIService;
import org.ssssssss.magicapi.core.service.MagicNotifyService;

import java.util.Properties;

@Configuration
@EnableConfigurationProperties(NacosConfig.class)
public class MagicAPINacosConfiguration implements MagicPluginConfiguration {

    private final MagicAPIProperties properties;
    private final NacosConfig nacosConfig;
    private final ApplicationContext applicationContext;

    public MagicAPINacosConfiguration(MagicAPIProperties properties, NacosConfig nacosConfig, ApplicationContext applicationContext){
        this.properties = properties;
        this.nacosConfig = nacosConfig;
        this.applicationContext = applicationContext;
    }

    @Override
    public Plugin plugin() {
        return new Plugin("Nacos插件");
    }

    @Bean
    @ConditionalOnProperty(prefix = "magic-api.nacos",name = "enable-discovery",havingValue = "true")
    public NacosDiscovery nacosDiscovery() throws NacosException {
        return new NacosDiscovery(properties,nacosConfig,applicationContext);
    }

    @Bean
    @ConditionalOnProperty(prefix = "magic-api.nacos",name = "enable-discovery",havingValue = "true")
    public RpcModule rpcFunction(NacosDiscovery nacosDiscovery){
        RpcModule rpcModule = new RpcModule(nacosDiscovery.getNamingService());
        return rpcModule;
    }

    @Bean
    @ConditionalOnProperty(prefix = "magic-api.nacos",name = "enable-config",havingValue = "true")
    public NacosConfigModule nacosConfigModule() throws NacosException {
        return new NacosConfigModule(getConfigService(),nacosConfig);
    }

    /**
     * 使用Nacos配置通知
     */
    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = "magic-api.nacos",name = "enable-discovery",havingValue = "true")
    public MagicNotifyService magicNotifyService() {
        Environment env = applicationContext.getEnvironment();
        String dataclusterid = env.getProperty("spring.application.name")+"-cluster";
        return magicNotify -> {
            try {
                getConfigService().publishConfig(dataclusterid, nacosConfig.getGroup(), JSONUtil.parseObj(magicNotify,false).toStringPretty(), ConfigType.JSON.getType());
            } catch (NacosException e) {
                throw new RuntimeException(e);
            }
        };
    }

    /**
     * 消息处理服务
     */
    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnProperty(prefix = "magic-api.nacos",name = "enable-discovery",havingValue = "true")
    public MagicSynchronizationService magicSynchronizationService(MagicNotifyService magicNotifyService) {
        return new MagicSynchronizationService(magicNotifyService, properties.getInstanceId());
    }

    /**
     * 使用Nacos配置监听
     */
    @Bean
    @ConditionalOnProperty(prefix = "magic-api.nacos",name = "enable-discovery",havingValue = "true")
    public NacosClusterListener nacosClusterListener(MagicAPIService magicAPIService) throws NacosException {
        return new NacosClusterListener(getConfigService(),nacosConfig,magicAPIService,applicationContext);
    }

    private ConfigService getConfigService() throws NacosException {
        Properties properties = new Properties();
        properties.put("serverAddr", nacosConfig.getServerAddr());
        if (nacosConfig.isEnabledAuth()){
            properties.put("username",nacosConfig.getUsername());
            properties.put("password",nacosConfig.getPassword());
        }
        ConfigService configService = NacosFactory.createConfigService(properties);
        return configService;
    }
}
